/* Contains basic matrix operations, the mathematical ones. */

#ifndef _MATRIX_H_
#define _MATRIX_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "misc.h"

/* Matrix layout */
#define ROWMAJOR 1
#define COLMAJOR 2

/* Let's make matrix a data structure, so that things are nice */
typedef struct {
    int row;
    int col;
    int major;

    double *data;    /* Pointer to (row x col x sizeof(double)) sized 
                       memory region */
} matrix;

/* Easy transformation from 2D coordinates to 1D coordinates 
   The convention used is the one used most commonly, i.e:
        A_ij is the element of i'th row and j'th column.
*/
static inline int _to1(matrix *A, int i, int j) {
    if (A->major == ROWMAJOR) 
        return (j + i*(A->col));
    else if (A->major == COLMAJOR)
        return (j*(A->row) + i);
    return _EMISC;          /* This is _EMISC */
}

#define MAT_ELEM(mat,i,j) (mat)->data[_to1(mat,(i),(j))]


/* Initializes a matrix of size row X col, and allocates memory for the actual data too */
int init_mat(matrix *A, int row, int col);

/* Frees up the memory allocated for holding actual data */
void dest_mat(matrix *A);

/* Adds 2 matrices. Also init's the matrix res */
int add_mat(matrix *A, matrix *B, matrix *res);

/* Scalar mult. Also init's the matrix res */
int mult_scalar(matrix *A, double t, matrix *res);

/* Matrix mult. Also init's the matrix res */
int mult_mat(matrix *A, matrix *B, matrix *res);

/* Matrix Transpose. Also init's the matrix res */
int trans_mat(matrix *A, matrix *res);

#ifdef __cplusplus
}
#endif

#endif /* _MATRIX_H_ */
